//
//  BluetoothManager.m
//  Saas
//
//  Created by 杨荣 on 2020/6/1.
//  Copyright © 2020 bing. All rights reserved.
//

#import "BluetoothManager.h"

@interface BluetoothManager()<CBCentralManagerDelegate,CBPeripheralDelegate>

/* 扫描 */
@property (nonatomic,copy) ScanSuccess scanSuccess;// 扫描成功回调
@property (nonatomic,copy) ScanFailure scanFailure;// 扫描失败回调

/* 连接 */
@property (nonatomic,copy) DidConnectPeripheral didConnectPeripheral;// 连接成功回调
@property (nonatomic,copy) DidFailToConnectPeripheral didFailToConnectPeripheral;// 连接失败回调
@property (nonatomic,copy) DidDisconnectPeripheral didDisconnectPeripheral;// 失去连接回调

/* 写入 */
@property (nonatomic,copy) WriteToPeripheralSuccess writeToPeripheralSuccess;// 写入成功
@property (nonatomic,copy) WriteToPeripheralFailure writeToPeripheralFailure;// 写入失败

/* 接收 */
@property (nonatomic,copy) DidReceiveDataFromPeripheral didReceiveDataFromPeripheral;// 已经从外设中接收到数据





/* 中心 */
@property (nonatomic,strong) CBCentralManager *centralManager;// 中心设备管理

/* 外设 */
@property (nonatomic,strong) NSMutableArray <CBPeripheral *>*peripheralArray;// 外设列表
@property (nonatomic,strong) CBPeripheral *connectedPeripheral;// 已经连接的外设
@property (nonatomic,strong) CBCharacteristic *connectedCharacteristic;// 已经连接的外设的特征


@property (nonatomic,copy) NSData *writeData;// 写入的数据


@end

@implementation BluetoothManager

static BluetoothManager *instance = nil;
+ (instancetype)sharedInstance {
    return [[self alloc] init];
}
- (instancetype)init {
    static dispatch_once_t onceToken;
    dispatch_once(&onceToken, ^{
        instance = [super init];
    });
    return instance;
}
+ (instancetype)allocWithZone:(struct _NSZone *)zone{
    static dispatch_once_t onceToken;
    dispatch_once(&onceToken, ^{
        instance = [super allocWithZone:zone];
    });
    return instance;
}


- (NSMutableArray <CBPeripheral *>*)peripheralArray {
    if (!_peripheralArray) {
        _peripheralArray  = [NSMutableArray array];
    }
    return _peripheralArray;
}


#pragma mark --------------- 中心 ---------------
#pragma mark 扫描
- (void)scanWithSuccess:(ScanSuccess)scanSuccess failure:(ScanFailure)scanFailure {
    NSLog(@"扫描");
    
    self.scanSuccess = scanSuccess;
    self.scanFailure = scanFailure;
    
    [self.peripheralArray removeAllObjects];
    self.centralManager = [[CBCentralManager alloc] initWithDelegate:self queue:dispatch_get_main_queue()];
}
#pragma mark 停止扫描
- (void)stopScan {
    NSLog(@"停止扫描");
    
    [self.centralManager stopScan];
}
#pragma mark 取消连接
- (void)cancelConnect {
    NSLog(@" 取消连接");
    
    if (self.connectedPeripheral) {
        [self.centralManager cancelPeripheralConnection:self.connectedPeripheral];
    }
}

#pragma mark <CBCentralManagerDelegate>
#pragma mark CBCentralManagerDelegate  已经扫描到一个外设
- (void)centralManager:(CBCentralManager *)central didDiscoverPeripheral:(CBPeripheral *)peripheral advertisementData:(NSDictionary<NSString *, id> *)advertisementData RSSI:(NSNumber *)RSSI {
    NSLog(@"CBCentralManagerDelegate  已经扫描到一个外设");
    
    if (peripheral.name.length > 0 && ![self.peripheralArray containsObject:peripheral]) {
        [self.peripheralArray addObject:peripheral];
    }
    if (self.scanSuccess) {
        self.scanSuccess((NSArray *)self.peripheralArray);
    }
}

#pragma mark 连接
- (void)connect:(CBPeripheral *)peripheral didConnectPeripheral:(DidConnectPeripheral)didConnectPeripheral didFailToConnectPeripheral:(DidFailToConnectPeripheral)didFailToConnectPeripheral didDisconnectPeripheral:(DidDisconnectPeripheral)didDisconnectPeripheral {
    NSLog(@"连接蓝牙");
    
    self.didConnectPeripheral = didConnectPeripheral;
    self.didFailToConnectPeripheral = didFailToConnectPeripheral;
    self.didDisconnectPeripheral = didDisconnectPeripheral;
    
    [self.centralManager connectPeripheral:peripheral options:@{CBCentralManagerRestoredStateScanOptionsKey:@(YES)}];
    peripheral.delegate = self;
    
}
#pragma mark CBCentralManagerDelegate  已经连接到外设
- (void)centralManager:(CBCentralManager *)central didConnectPeripheral:(CBPeripheral *)peripheral {
    NSLog(@"CBCentralManagerDelegate  已经连接到外设");
    
    [self.centralManager stopScan];
    self.connectedPeripheral = peripheral;
    if (self.didConnectPeripheral) {
        self.didConnectPeripheral(peripheral);
    }
    
}

#pragma mark CBCentralManagerDelegate  连接外设失败
- (void)centralManager:(CBCentralManager *)central didFailToConnectPeripheral:(CBPeripheral *)peripheral error:(nullable NSError *)error {
    NSLog(@"CBCentralManagerDelegate  连接外设失败");
    
    self.connectedPeripheral = nil;
    if (self.didFailToConnectPeripheral) {
        self.didFailToConnectPeripheral(peripheral, error);
    }
}

#pragma mark CBCentralManagerDelegate  蓝牙状态已经改变
- (void)centralManagerDidUpdateState:(CBCentralManager *)central {
    NSLog(@"CBCentralManagerDelegate  蓝牙状态已经改变");
    
    NSString *state = nil;
    switch ([central state])
    {
        case CBCentralManagerStateUnknown:
            state = @"未知状态";
            if (self.scanFailure) {
                self.scanFailure((CBCentralManagerState)[central state], state);
            }
            break;
        case CBCentralManagerStateResetting:
            state = @"正在重置状态";
            if (self.scanFailure) {
                self.scanFailure((CBCentralManagerState)[central state], state);
            }
            break;
        case CBCentralManagerStateUnsupported:
            state = @"该设备不支持蓝牙";
            if (self.scanFailure) {
                self.scanFailure((CBCentralManagerState)[central state], state);
            }
            break;
        case CBCentralManagerStateUnauthorized:
            state = @"应用未授权使用蓝牙";
            if (self.scanFailure) {
                self.scanFailure((CBCentralManagerState)[central state], state);
            }
            break;
        case CBCentralManagerStatePoweredOff:
            state = @"蓝牙未打开";
            if (self.scanFailure) {
                self.scanFailure((CBCentralManagerState)[central state], state);
            }
            break;
        case CBCentralManagerStatePoweredOn:
            state = @"蓝牙可用";
            [self.centralManager scanForPeripheralsWithServices:nil options:@{CBCentralManagerRestoredStateScanOptionsKey:@(YES)}];
            break;
            
        default:
            break;
    }
}

#pragma mark CBCentralManagerDelegate  已经断开连接
- (void)centralManager:(CBCentralManager *)central didDisconnectPeripheral:(CBPeripheral *)peripheral error:(nullable NSError *)error {
    NSLog(@"CBCentralManagerDelegate  已经断开连接");
    
    self.connectedPeripheral = nil;
    if (self.didDisconnectPeripheral) {
        self.didDisconnectPeripheral(peripheral, error);
    }
}


#pragma mark --------------- 外设 ---------------
#pragma mark 写入
- (void)writeToPeripheralWithData:(NSData *)data success:(WriteToPeripheralSuccess)success failure:(WriteToPeripheralFailure)failure {
    self.writeToPeripheralSuccess = success;
    self.writeToPeripheralFailure = failure;
    
    if (!data || data.length <= 0) {
        NSLog(@"写入数据为空");
        if (self.writeToPeripheralFailure) {
            self.writeToPeripheralFailure(@"写入数据为空");
        }
        return;
    }
    
    if (!self.connectedPeripheral) {
        NSLog(@"未连接外设");
        if (self.writeToPeripheralFailure) {
            self.writeToPeripheralFailure(@"未连接外设");
        }
        return;
    }
    
    self.writeData = data;
    [self.connectedPeripheral discoverServices:nil];// 连接外设 -> 外设服务
}

#pragma mark 接收
- (void)didReceiveDataFromPeripheral:(DidReceiveDataFromPeripheral)didReceiveDataFromPeripheral {
    self.didReceiveDataFromPeripheral = didReceiveDataFromPeripheral;
}
#pragma mark <CBPeripheralDelegate>
#pragma mark CBPeripheralDelegate 从外设中已经发现服务
- (void)peripheral:(CBPeripheral *)peripheral didDiscoverServices:(nullable NSError *)error {
    NSLog(@"CBPeripheralDelegate 从外设中已经发现服务");
    if (error) {
        NSLog(@"error = %@",error.localizedDescription);
        return;
    }
    
    // 外设服务 -> 外设特征
    self.connectedCharacteristic = nil;
    for (CBService *service in peripheral.services) {
        [peripheral discoverCharacteristics:nil forService:service];
    }
}

#pragma mark CBPeripheralDelegate 从外设服务中已经发现特征
- (void)peripheral:(CBPeripheral *)peripheral didDiscoverCharacteristicsForService:(CBService *)service error:(nullable NSError *)error {
    NSLog(@"CBPeripheralDelegate 从外设服务中已经发现特征");
    if (error) {
        NSLog(@"error = %@",error.localizedDescription);
        return;
    }
    
    if (!self.connectedCharacteristic) {
        for (CBCharacteristic *characteristic in service.characteristics) {
            [peripheral setNotifyValue:YES forCharacteristic:characteristic];
            if (characteristic.properties & CBCharacteristicPropertyWrite) {
                NSLog(@"CBPeripheralDelegate 从外设服务中已经发现特征----->可写");
                self.connectedCharacteristic = characteristic;
                
                [self writeValue];
                return;
            }
            
        }
    }
    
    
    //    for (CBCharacteristic *characteristic in service.characteristics) {
    //        CBCharacteristicProperties properties = characteristic.properties;
    //        [peripheral setNotifyValue:YES forCharacteristic:characteristic];
    //
    //        if (properties & CBCharacteristicPropertyWrite) {
    //            self.connectedCharacteristic = characteristic;
    //
    //
    //            [self writeValue];
    //            return;
    //
    //        }
    //
    //    }
}

#pragma mark CBPeripheralDelegate 从外设中接收到数据
- (void)peripheral:(CBPeripheral *)peripheral didUpdateValueForCharacteristic:(CBCharacteristic *)characteristic error:(nullable NSError *)error {
    NSLog(@"CBPeripheralDelegate 从外设中接收到数据");
    if (error) {
        NSLog(@"error = %@",error.localizedDescription);
        return;
    }
    
    if (characteristic.value) {
        NSData *data = characteristic.value;
        if (data.length > 0) {
            const unsigned char *hexBytesLight = [data bytes];
            NSString *battery = [NSString stringWithFormat:@"%s", hexBytesLight];
            if (self.didReceiveDataFromPeripheral) {
                self.didReceiveDataFromPeripheral(battery);
            }
            
        }
    }
    
}

#pragma mark CBPeripheralDelegate 已经将数据写入到外设
- (void)peripheral:(CBPeripheral *)peripheral didWriteValueForCharacteristic:(CBCharacteristic *)characteristic error:(nullable NSError *)error {
    NSLog(@"CBPeripheralDelegate 已经将数据写入到外设");
    if (error) {
        NSLog(@"error = %@",error.localizedDescription);
        return;
    }
}



- (void)writeValue {
    NSData *data = self.writeData;
    if (self.connectedCharacteristic.properties & CBCharacteristicPropertyWrite) {
        
        NSInteger sendDataLengthMax = 100;
        if (data.length <= sendDataLengthMax) {
            [self.connectedPeripheral writeValue:data forCharacteristic:self.connectedCharacteristic type:CBCharacteristicWriteWithResponse];
        } else {
            NSInteger index = 0;
            for (index = 0; index < data.length - sendDataLengthMax; index += sendDataLengthMax) {
                NSData *subData = [data subdataWithRange:NSMakeRange(index, sendDataLengthMax)];
                [self.connectedPeripheral writeValue:subData forCharacteristic:self.connectedCharacteristic type:CBCharacteristicWriteWithResponse];
            }
            NSData *leftData = [data subdataWithRange:NSMakeRange(index, data.length - index)];
            if (leftData) {
                [self.connectedPeripheral writeValue:leftData forCharacteristic:self.connectedCharacteristic type:CBCharacteristicWriteWithResponse];
            }
        }
        NSLog(@"正在写入");
        if (self.writeToPeripheralSuccess) {
            self.writeToPeripheralSuccess();
        }
        
    }else{
        NSLog(@"不支持写入");
        if (self.writeToPeripheralFailure) {
            self.writeToPeripheralFailure(@"不支持写入");
        }
    }
}

@end
